#pragma once
#include "requestor.hpp"
// 意义：向用户提供进行rpc调用的模块
namespace rpc
{
    namespace client
    {
        class RpcCaller
        {
            public:
            using ptr=std::shared_ptr<RpcCaller>;
            RpcCaller(Requestor::ptr requestor) : _requestor(requestor) {}
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallback = std::function<void(const Json::Value &)>;
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, Json::Value &result)
            {
                // 1.组织请求
                auto req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMType(MType::REQ_RPC);
                req->setMethod(method);
                req->setPara(params);
                BaseMessage::ptr rsp_msg;
                // 2.发送请求
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req), rsp_msg);
                if (ret == false)
                {
                    ELOG("同步rpc请求发送失败");
                    return false;
                }
                // 3.等待响应
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc请求出错:%s", errorReason(rpc_rsp_msg->rcode()).c_str());
                    return false;
                }
                result = rpc_rsp_msg->Result();
                return true;
            }
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, JsonAsyncResponse &result)
            {
                // 向服务器发送异步回调请求，设置回调函数，回调函数会传入一个promise对象，在回调函数中去对promise设置数据
                auto req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMType(MType::REQ_RPC);
                req->setMethod(method);
                req->setPara(params);
                BaseMessage::ptr rsp_msg;
                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallback cb = std::bind(&RpcCaller::callback, this, json_promise,
                                                          std::placeholders::_1);
                // 2.发送请求

                bool ret = _requestor->send(conn, req, cb);
                if (ret == false)
                {
                    ELOG("同步rpc请求发送失败");
                    return false;
                }
                return true;
            }
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, const JsonResponseCallback &cb)
            {
                auto req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setMType(MType::REQ_RPC);
                req->setMethod(method);
                req->setPara(params);
                Requestor::RequestCallback req_cb=std::bind(&RpcCaller::callback1, 
                    this, cb, std::placeholders::_1);
                    bool ret = _requestor->send(conn, 
                    std::dynamic_pointer_cast<BaseMessage>(req), 
                   req_cb);
                   if(ret==false)
                   {
                    ELOG("回调rpc请求失败");
                    return false;
                   }
                   return true;
            }//?

        private:
            void callback1(const JsonResponseCallback &cb,
                           const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc请求出错:%s", errorReason(rpc_rsp_msg->rcode()).c_str());
                    return;
                }
                cb(rpc_rsp_msg->Result());
            }
            void callback(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    ELOG("rpc请求出错:%s", errorReason(rpc_rsp_msg->rcode()).c_str());
                    return;
                }
                result->set_value(rpc_rsp_msg->Result());
            }

        private:
            Requestor::ptr _requestor;
        };
    }
}